<?php
declare(strict_types=1);

namespace SixShop\MakerBundle;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Style\SymfonyStyle;
use SixShop\MakerBundle\Generator\MigrationGenerator;
use SixShop\MakerBundle\Generator\ComposerGenerator;
use SixShop\MakerBundle\Generator\ModelGenerator;
use SixShop\MakerBundle\Generator\EntityGenerator;
use SixShop\MakerBundle\Generator\ControllerGenerator;
use SixShop\MakerBundle\Generator\RouteUpdater;

class MigrationMaker extends Command
{
    protected static $defaultName = 'create_migration';
    protected static $defaultDescription = '生成数据库迁移文件、模型、实体、控制器和路由';
    
    private MigrationGenerator $migrationGenerator;
    private ComposerGenerator $composerGenerator;
    private ModelGenerator $modelGenerator;
    private EntityGenerator $entityGenerator;
    private ControllerGenerator $controllerGenerator;
    private RouteUpdater $routeUpdater;
    
    public function __construct()
    {
        parent::__construct();
        $this->migrationGenerator = new MigrationGenerator();
        $this->composerGenerator = new ComposerGenerator();
        $this->modelGenerator = new ModelGenerator();
        $this->entityGenerator = new EntityGenerator();
        $this->controllerGenerator = new ControllerGenerator();
        $this->routeUpdater = new RouteUpdater();
        $this->setAliases(['cm']);
    }

    protected function configure(): void
    {
        $this->setName('create_migration')
             ->setDescription(self::$defaultDescription)
             ->addOption('action', 'a', InputOption::VALUE_OPTIONAL, '操作类型 (create|add_column|drop_column|modify)', 'create');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        
        // Get target path for the SixShop extension
        $targetPath = $this->getTargetPath($io);
        if (!$targetPath) {
            return Command::FAILURE;
        }
        
        // Get extension information from composer.json
        $extensionInfo = $this->composerGenerator->gatherPackageInfo($io, $targetPath);
        if (!$extensionInfo) {
            return Command::FAILURE;
        }
        
        $io->title("生成数据库迁移文件、模型、实体、控制器和路由");
        $io->section("扩展信息");
        $io->table(
            ['属性', '值'],
            [
                ['包名', $extensionInfo['packageName']],
                ['命名空间', $extensionInfo['namespace']],
                ['扩展ID', $extensionInfo['id']]
            ]
        );
        
        // Get table information
        $tableName = $io->ask('请输入表名');
        if (empty($tableName)) {
            $io->error('表名不能为空!');
            return Command::FAILURE;
        }
        
        $tableComment = $io->ask('请输入表注释 (可选)', '');
        
        $action = $input->getOption('action');
        
        // Set migration path in the migrations directory of the target path
        $migrationPath = $targetPath . '/database/migrations';
        $this->migrationGenerator->setMigrationsPath($migrationPath);
        
        $io->section("表名: {$tableName}");
        $io->section("操作类型: {$action}");
        if (!empty($tableComment)) {
            $io->section("表注释: {$tableComment}");
        }
        $io->note("迁移文件将保存在: {$migrationPath}");
        
        // Get field definitions based on action
        $fields = [];
        switch ($action) {
            case 'create':
                $fields = $this->getCreateTableFields($io);
                break;
            case 'add_column':
                $fields = $this->getAddColumnFields($io);
                break;
            case 'drop_column':
                $fields = $this->getDropColumnFields($io);
                break;
            case 'modify':
                $fields = $this->getModifyTableFields($io);
                break;
            default:
                $io->error("不支持的操作类型: {$action}");
                return Command::FAILURE;
        }
        
        // Generate migration
        if (!$this->migrationGenerator->generateMigration($tableName, $fields, $action, $io)) {
            return Command::FAILURE;
        }
        
        // Generate model and entity if creating a new table
        if ($action === 'create') {
            $io->section('生成相关模型和实体文件');
            
            if (!$this->generateModelAndEntity($tableName, $tableComment, $fields, $extensionInfo, $targetPath, $io)) {
                $io->warning('迁移文件生成成功，但模型/实体生成失败');
                return Command::FAILURE;
            }
            
            // Generate controllers after entity generation
            $io->section('生成控制器文件');
            
            if (!$this->generateControllers($tableName, $tableComment, $fields, $extensionInfo, $targetPath, $io)) {
                $io->warning('模型/实体生成成功，但控制器生成失败');
                return Command::FAILURE;
            }
            
            // Update route files after controller generation
            $io->section('更新路由文件');
            
            if (!$this->updateRoutes($tableName, $tableComment, $extensionInfo, $targetPath, $io)) {
                $io->warning('控制器生成成功，但路由更新失败');
                return Command::FAILURE;
            }
        }
        
        $io->success('迁移文件和相关文件生成完成!');
        return Command::SUCCESS;
    }
    
    /**
     * Get fields for create table action
     */
    private function getCreateTableFields(SymfonyStyle $io): array
    {
        $fields = [];
        $supportedTypes = $this->migrationGenerator->getSupportedFieldTypes();
        
        $io->section('定义表字段');
        $io->note('支持的字段类型: ' . implode(', ', $supportedTypes));
        
        while (true) {
            $fieldName = $io->ask('字段名 (回车结束字段定义)');
            if (empty($fieldName)) {
                break;
            }
            
            $fieldType = $io->choice('字段类型', $supportedTypes, 'string');
            
            $field = [
                'name' => $fieldName,
                'type' => $fieldType
            ];
            
            // Get field options
            $field = array_merge($field, $this->getFieldOptions($io, $fieldType));
            
            $fields[] = $field;
            
            $io->text("已添加字段: {$fieldName} ({$fieldType})");
        }
        
        return $fields;
    }
    
    /**
     * Get fields for add column action
     */
    private function getAddColumnFields(SymfonyStyle $io): array
    {
        return $this->getCreateTableFields($io); // Same logic for adding columns
    }
    
    /**
     * Get fields for drop column action
     */
    private function getDropColumnFields(SymfonyStyle $io): array
    {
        $fields = [];
        
        $io->section('选择要删除的字段');
        
        while (true) {
            $fieldName = $io->ask('要删除的字段名 (回车结束)');
            if (empty($fieldName)) {
                break;
            }
            
            $fields[] = ['name' => $fieldName];
            $io->text("已添加删除字段: {$fieldName}");
        }
        
        return $fields;
    }
    
    /**
     * Get fields for modify table action
     */
    private function getModifyTableFields(SymfonyStyle $io): array
    {
        $io->section('修改表结构');
        $io->note('此操作将生成一个空的迁移模板，您需要手动添加修改逻辑');
        return [];
    }
    
    /**
     * Get field options based on field type
     */
    private function getFieldOptions(SymfonyStyle $io, string $fieldType): array
    {
        $options = [];
        
        // Length/limit
        if (in_array($fieldType, ['string', 'binary'])) {
            $length = $io->ask('字段长度 (可选)', null);
            if ($length !== null) {
                $options['length'] = (int)$length;
            }
        }
        
        // Decimal precision and scale
        if ($fieldType === 'decimal') {
            $precision = $io->ask('精度 (总位数)', '10');
            $scale = $io->ask('小数点位数', '2');
            $options['precision'] = (int)$precision;
            $options['scale'] = (int)$scale;
        }
        
        // Nullable
        $options['null'] = $io->confirm('允许为空?', true);
        
        // Default value
        $defaultValue = $io->ask('默认值 (可选)', null);
        if ($defaultValue !== null) {
            // Convert string representations of boolean/null
            if (strtolower($defaultValue) === 'true') {
                $options['default'] = true;
            } elseif (strtolower($defaultValue) === 'false') {
                $options['default'] = false;
            } elseif (strtolower($defaultValue) === 'null') {
                $options['default'] = null;
            } else {
                $options['default'] = $defaultValue;
            }
        }
        
        // Comment
        $comment = $io->ask('字段备注 (可选)', null);
        if ($comment !== null) {
            $options['comment'] = $comment;
        }
        
        // Index options
        $options['index'] = $io->confirm('创建索引?', false);
        if (!$options['index']) {
            $options['unique'] = $io->confirm('创建唯一索引?', false);
        }
        
        return $options;
    }
    
    /**
     * Interactive field builder
     */
    private function buildFieldInteractively(SymfonyStyle $io): array
    {
        $fields = [];
        $supportedTypes = $this->migrationGenerator->getSupportedFieldTypes();
        
        $io->section('交互式字段构建器');
        $io->note('您可以逐个定义表字段，支持的类型: ' . implode(', ', $supportedTypes));
        
        $continueAdding = true;
        while ($continueAdding) {
            $fieldName = $io->ask('字段名');
            if (empty($fieldName)) {
                break;
            }
            
            $fieldType = $io->choice('字段类型', $supportedTypes, 'string');
            
            $field = [
                'name' => $fieldName,
                'type' => $fieldType
            ];
            
            // Get additional options
            $field = array_merge($field, $this->getFieldOptions($io, $fieldType));
            
            $fields[] = $field;
            
            // Show field summary
            $summary = "字段: {$field['name']} ({$field['type']})";
            if (isset($field['length'])) {
                $summary .= " 长度:{$field['length']}";
            }
            if (isset($field['null']) && !$field['null']) {
                $summary .= " NOT NULL";
            }
            if (isset($field['default'])) {
                $summary .= " 默认:{$field['default']}";
            }
            
            $io->text("✓ 已添加 - {$summary}");
            
            $continueAdding = $io->confirm('继续添加字段?', true);
        }
        
        return $fields;
    }
    
    /**
     * 获取用户输入的目标路径
     */
    private function getTargetPath(SymfonyStyle $io): ?string
    {
        try {
            // 获取当前工作目录作为默认值
            $defaultPath = getcwd();
            
            $targetPath = $io->ask(
                '请输入SixShop扩展目标路径 (绝对路径或相对路径)',
                $defaultPath
            );
            
            if (empty($targetPath)) {
                throw new \InvalidArgumentException('目标路径不能为空!');
            }
            
            // 转换为绝对路径
            $absolutePath = realpath($targetPath);
            if ($absolutePath === false) {
                // 如果路径不存在，尝试创建它
                if (!is_dir($targetPath)) {
                    $io->note('目标路径不存在，尝试创建目录: ' . $targetPath);
                    if (!mkdir($targetPath, 0755, true)) {
                        throw new \InvalidArgumentException('无法创建目标路径: ' . $targetPath);
                    }
                }
                $absolutePath = realpath($targetPath);
            }
            
            // 检查路径是否可写
            if (!is_writable($absolutePath)) {
                throw new \InvalidArgumentException('目标路径不可写: ' . $absolutePath);
            }
            
            $io->note('将在以下扩展路径生成迁移文件: ' . $absolutePath . '/database/migrations');
            
            // 确认路径
            if (!$io->confirm('确认使用此路径?', true)) {
                return $this->getTargetPath($io); // 递归重新获取路径
            }
            
            return $absolutePath;
            
        } catch (\InvalidArgumentException $e) {
            $io->error($e->getMessage());
            return null;
        }
    }
    
    /**
     * 生成模型和实体文件
     */
    private function generateModelAndEntity(string $tableName, string $tableComment, array $fields, array $extensionInfo, string $targetPath, SymfonyStyle $io): bool
    {
        try {
            // Generate model file
            $modelResult = $this->modelGenerator->generateModel(
                $tableName, 
                $tableComment, 
                $fields, 
                $extensionInfo, 
                $targetPath, 
                $io
            );
            
            // Generate entity file
            $entityResult = $this->entityGenerator->generateEntity(
                $tableName, 
                $tableComment, 
                $fields, 
                $extensionInfo, 
                $targetPath, 
                $io
            );
            
            return $modelResult && $entityResult;
            
        } catch (\Exception $e) {
            $io->error('生成模型和实体文件时发生错误: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 生成控制器文件
     */
    private function generateControllers(string $tableName, string $tableComment, array $fields, array $extensionInfo, string $targetPath, SymfonyStyle $io): bool
    {
        try {
            return $this->controllerGenerator->generateControllers(
                $tableName, 
                $tableComment, 
                $fields, 
                $extensionInfo, 
                $targetPath, 
                $io
            );
            
        } catch (\Exception $e) {
            $io->error('生成控制器文件时发生错误: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 更新路由文件
     */
    private function updateRoutes(string $tableName, string $tableComment, array $extensionInfo, string $targetPath, SymfonyStyle $io): bool
    {
        try {
            return $this->routeUpdater->updateRoutes(
                $tableName, 
                $tableComment, 
                $extensionInfo, 
                $targetPath, 
                $io
            );
            
        } catch (\Exception $e) {
            $io->error('更新路由文件时发生错误: ' . $e->getMessage());
            return false;
        }
    }
}